package handler

import (
	"github.com/gin-gonic/gin"
	"github.com/honwee/awm/internal/api/dto"
	"github.com/honwee/awm/internal/service"
	"github.com/honwee/awm/pkg/logger"
	"go.uber.org/zap"
	"net/http"
)

type TraceHandler struct {
	traceService *service.TraceService
	log          *zap.SugaredLogger
}

func NewTraceHandler(traceService *service.TraceService) *TraceHandler {
	return &TraceHandler{
		traceService: traceService,
		log:          logger.Logger.Sugar(),
	}
}

// GetWorkflowTraces godoc
// @Summary 获取工作流的所有追踪日志
// @Description 根据工作流ID获取所有相关的追踪日志
// @Tags 追踪日志
// @Accept json
// @Produce json
// @Param workflow_id path string true "工作流ID"
// @Param page query int false "页码（从1开始）" default(1) minimum(1)
// @Param page_size query int false "每页大小" default(10) minimum(1) maximum(100)
// @Success 200 {object} dto.TraceListResponse
// @Failure 400 {object} map[string]string
// @Failure 500 {object} map[string]string
// @Router /traces/workflow/{workflow_id} [get]
func (h *TraceHandler) GetWorkflowTraces(c *gin.Context) {
	workflowID := c.Param("workflow_id")
	if workflowID == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "workflow_id is required"})
		return
	}

	var pagination dto.PaginationQuery
	if err := c.ShouldBindQuery(&pagination); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	traces, total, err := h.traceService.GetWorkflowTraces(workflowID, pagination.GetOffset(), pagination.GetLimit())
	if err != nil {
		h.log.Errorw("Failed to get workflow traces",
			"workflow_id", workflowID,
			"error", err)
		c.Error(err)
		return
	}

	response := &dto.TraceListResponse{}
	response.FromModelList(traces, pagination.Page, pagination.PageSize, total)
	c.JSON(http.StatusOK, response)
}

// GetWorkflowRunTraces godoc
// @Summary 获取工作流运行实例的所有追踪日志
// @Description 根据工作流运行ID获取所有相关的追踪日志
// @Tags 追踪日志
// @Accept json
// @Produce json
// @Param workflow_run_id path string true "工作流运行ID"
// @Param page query int false "页码（从1开始）" default(1) minimum(1)
// @Param page_size query int false "每页大小" default(10) minimum(1) maximum(100)
// @Success 200 {object} dto.TraceListResponse
// @Failure 400 {object} map[string]string
// @Failure 500 {object} map[string]string
// @Router /traces/workflow-run/{workflow_run_id} [get]
func (h *TraceHandler) GetWorkflowRunTraces(c *gin.Context) {
	workflowRunID := c.Param("workflow_run_id")
	if workflowRunID == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "workflow_run_id is required"})
		return
	}

	var pagination dto.PaginationQuery
	if err := c.ShouldBindQuery(&pagination); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	traces, total, err := h.traceService.GetWorkflowRunTraces(workflowRunID, pagination.GetOffset(), pagination.GetLimit())
	if err != nil {
		h.log.Errorw("Failed to get workflow run traces",
			"workflow_run_id", workflowRunID,
			"error", err)
		c.Error(err)
		return
	}

	response := &dto.TraceListResponse{}
	response.FromModelList(traces, pagination.Page, pagination.PageSize, total)
	c.JSON(http.StatusOK, response)
}

// GetNodeRunTraces godoc
// @Summary 获取节点运行实例的所有追踪日志
// @Description 根据节点运行ID获取所有相关的追踪日志
// @Tags 追踪日志
// @Accept json
// @Produce json
// @Param node_run_id path string true "节点运行ID"
// @Param page query int false "页码（从1开始）" default(1) minimum(1)
// @Param page_size query int false "每页大小" default(10) minimum(1) maximum(100)
// @Success 200 {object} dto.TraceListResponse
// @Failure 400 {object} map[string]string
// @Failure 500 {object} map[string]string
// @Router /traces/node-run/{node_run_id} [get]
func (h *TraceHandler) GetNodeRunTraces(c *gin.Context) {
	nodeRunID := c.Param("node_run_id")
	if nodeRunID == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "node_run_id is required"})
		return
	}

	var pagination dto.PaginationQuery
	if err := c.ShouldBindQuery(&pagination); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	traces, total, err := h.traceService.GetNodeRunTraces(nodeRunID, pagination.GetOffset(), pagination.GetLimit())
	if err != nil {
		h.log.Errorw("Failed to get node run traces",
			"node_run_id", nodeRunID,
			"error", err)
		c.Error(err)
		return
	}

	response := &dto.TraceListResponse{}
	response.FromModelList(traces, pagination.Page, pagination.PageSize, total)
	c.JSON(http.StatusOK, response)
}

// GetNodeTraces godoc
// @Summary 获取节点的所有追踪日志
// @Description 根据节点ID获取所有相关的追踪日志
// @Tags 追踪日志
// @Accept json
// @Produce json
// @Param node_id path string true "节点ID"
// @Param page query int false "页码（从1开始）" default(1) minimum(1)
// @Param page_size query int false "每页大小" default(10) minimum(1) maximum(100)
// @Success 200 {object} dto.TraceListResponse
// @Failure 400 {object} map[string]string
// @Failure 500 {object} map[string]string
// @Router /traces/node/{node_id} [get]
func (h *TraceHandler) GetNodeTraces(c *gin.Context) {
	nodeID := c.Param("node_id")
	if nodeID == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "node_id is required"})
		return
	}

	var pagination dto.PaginationQuery
	if err := c.ShouldBindQuery(&pagination); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	traces, total, err := h.traceService.GetNodeTraces(nodeID, pagination.GetOffset(), pagination.GetLimit())
	if err != nil {
		h.log.Errorw("Failed to get node traces",
			"node_id", nodeID,
			"error", err)
		c.Error(err)
		return
	}

	response := &dto.TraceListResponse{}
	response.FromModelList(traces, pagination.Page, pagination.PageSize, total)
	c.JSON(http.StatusOK, response)
}

// GetTracesByEvent godoc
// @Summary 根据事件类型和其他条件获取追踪日志
// @Description 根据事件类型和可选的工作流ID、工作流运行ID、节点ID获取相关的追踪日志
// @Tags 追踪日志
// @Accept json
// @Produce json
// @Param event path string true "事件类型"
// @Param workflow_id query string false "工作流ID"
// @Param workflow_run_id query string false "工作流运行ID"
// @Param node_id query string false "节点ID"
// @Param page query int false "页码（从1开始）" default(1) minimum(1)
// @Param page_size query int false "每页大小" default(10) minimum(1) maximum(100)
// @Success 200 {object} dto.TraceListResponse
// @Failure 400 {object} map[string]string
// @Failure 500 {object} map[string]string
// @Router /traces/event/{event} [get]
func (h *TraceHandler) GetTracesByEvent(c *gin.Context) {
	event := c.Param("event")
	if event == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "event is required"})
		return
	}

	var pagination dto.PaginationQuery
	if err := c.ShouldBindQuery(&pagination); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 获取可选的查询参数
	workflowID := c.Query("workflow_id")
	workflowRunID := c.Query("workflow_run_id")
	nodeID := c.Query("node_id")

	traces, total, err := h.traceService.GetTracesByEvent(event, workflowID, workflowRunID, nodeID, pagination.GetOffset(), pagination.GetLimit())
	if err != nil {
		h.log.Errorw("Failed to get traces by event",
			"event", event,
			"workflow_id", workflowID,
			"workflow_run_id", workflowRunID,
			"node_id", nodeID,
			"error", err)
		c.Error(err)
		return
	}

	response := &dto.TraceListResponse{}
	response.FromModelList(traces, pagination.Page, pagination.PageSize, total)
	c.JSON(http.StatusOK, response)
}
